package com.liyunc.demo.service;
/**
 * Copyright (c) 2018-2022 ThunderSoft
 * All Rights Reserved by Thunder Software Technology Co., Ltd and its affiliates.
 * You may not use, copy, distribute, modify, transmit in any form this file
 * except in compliance with ThunderSoft in writing by applicable law.
 */

import com.liyunc.demo.model.dto.FileInfoDto;
import com.liyunc.demo.model.entity.FileInfo;
import com.liyunc.demo.service.base.BaseService;
import com.liyunc.demo.utils.ToDtoUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.Predicate;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author
 * @version 1.0
 * @file
 * @brief
 * @details
 * @date 2022-02-17
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2022-02-17                       Created
 */
@Service
public class FileService extends BaseService {

    /**
     * 获取所有文件列表.
     */
    public List<FileInfoDto> getAllFileList(final int startIndex, final int pageSize) {
        Sort sort = Sort.by(Sort.Direction.ASC, "id");
        Pageable pageable = PageRequest.of(startIndex, pageSize, sort);
        return fileInfoRepository
            .findAll(pageable)
            .stream()
            .map(ToDtoUtils::forInfoEntity)
            .collect(Collectors.toList());
    }

    /**
     * 根据项目id获取文件列表.
     */
    public List<FileInfoDto> getAllFileList(
        final int startIndex,
        final int pageSize,
        final Long projectId) {
        Sort sort = Sort.by(Sort.Direction.ASC, "id");
        Pageable pageable = PageRequest.of(startIndex, pageSize, sort);
        Specification<FileInfo> specification =
            (root, query, criteriaBuilder) -> {
                Predicate predicate = criteriaBuilder.equal(root.get("projectId"), projectId);
                return criteriaBuilder.and(predicate);
            };
        return fileInfoRepository
            .findAll(specification, pageable)
            .stream()
            .map(ToDtoUtils::forInfoEntity)
            .collect(Collectors.toList());
    }

    /**
     * 通过id获取文件.
     */
    public Optional<FileInfoDto> getSingleFile(long id) {
        return fileInfoRepository
            .findById(id)
            .map(ToDtoUtils::forInfoEntity);
    }

    /**
     * 创建文件.
     */
    public Optional<FileInfoDto> createFile(MultipartFile file, long projectId)
        throws IOException {
        if (authProject(projectId)) {
            try {
                FileInfo fileInfo = new FileInfo();
                fileInfo.setFileName(file.getName());
                fileInfo.setFilePath(file.getName());
                fileInfo.setCreateUser("zhangsan");
                fileInfo.setCreateTime(LocalDateTime.now());
                fileInfo.setLastUser("zhangsan");
                fileInfo.setLastTime(LocalDateTime.now());
                fileInfo.setKey(0);
                fileInfo.setProjectId(projectId);
                byte[] data = inputStreamToByte(file.getInputStream());
                fileInfo.setContent(data);
                FileInfo createInfo = fileInfoRepository.save(fileInfo);
                return Optional.of(createInfo).map(ToDtoUtils::forInfoEntity);
            } catch (IOException exception) {
                throw new IOException("file upload fail");
            }
        } else {
            return Optional.empty();
        }
    }

    /**
     * 删除文件.
     */
    public void deleteFile(long id) {
        fileInfoRepository.deleteById(id);
    }

    private byte[] inputStreamToByte(InputStream stream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        int ch;
        while ((ch = stream.read()) != -1) {
            outputStream.write(ch);
        }
        byte[] data = outputStream.toByteArray();
        outputStream.close();
        return data;
    }
}
